package com.fastjars.business.shiro.password;

import com.alibaba.fastjson.JSONObject;
import com.fastjars.business.spring.ContextHolder;
import com.fastjars.business.spring.cache.CacheManager;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * RetryLimitHashedCredentialsMatcher
 * 授权登录密码错误次数管理器
 * @author Brant Liu <br> 邮箱：<br>lbf1988@qq.com <br>日期：<br>2017/12/23
 * @version 1.0.0
 */
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    public final static Logger LOGGER = LoggerFactory.getLogger(RetryLimitHashedCredentialsMatcher.class);
    /**
     * 密码登录错误次数
     */
    public final static int              USER_LOGIN_ERROR_RETRY_COUNT = 2;
    /**
     * 缓存名称
     */
    public static final String           CACHE_NAME                   = "password-retry-cache";
    /**
     * 限制登录错误次数
     */
    private Integer                      errorMaxCount                = 5;

    private Cache<String, AtomicInteger> passwordRetryCache;

    public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
        this(CACHE_NAME,cacheManager);
    }

    public RetryLimitHashedCredentialsMatcher(String cacheName, CacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache(cacheName);
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        String username = (String) token.getPrincipal();
        AtomicInteger retryCount = passwordRetryCache.get(username);
        if (retryCount == null) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        if (retryCount.incrementAndGet() > this.getErrorMaxCount()) {
            throw new ExcessiveAttemptsException();
        }
        boolean matches = super.doCredentialsMatch(token, info);
        if (matches) {
            passwordRetryCache.remove(username);
        }
        return matches;
    }

    /**
     * 检查登录是否需要验证码
     * 尝试登录2次就需要验证码
     * @param username
     * @return
     */
    public static boolean checkCaptcha(String username){
        CacheManager cacheManager = ContextHolder.getBean(CacheManager.class);
        Cache<String, AtomicInteger> passwordRetryCache = cacheManager.getCache(RetryLimitHashedCredentialsMatcher.CACHE_NAME);
        if(null == passwordRetryCache){
            return false;
        }
        AtomicInteger retryCount = passwordRetryCache.get(username);
        if(LOGGER.isDebugEnabled()) {
            LOGGER.debug("尝试登录次数:" + JSONObject.toJSONString(retryCount));
        }
        if (retryCount == null) {
            return false;
        }
        if(retryCount.get() >= USER_LOGIN_ERROR_RETRY_COUNT){
            return true;
        }
        return false;
    }

    public Integer getErrorMaxCount() {
        return errorMaxCount;
    }

    public void setErrorMaxCount(Integer errorMaxCount) {
        this.errorMaxCount = errorMaxCount;
    }
}
